package com.hoodbrains.insideloc.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import android.content.Context;
import android.os.Environment;
import android.util.Log;

import com.hoodbrains.insideloc.locator.SuperMarketPOI;
import com.hoodbrains.insideloc.maps.Gondole;
import com.hoodbrains.insideloc.maps.Magasin;

/**
 * 
 * @author william.archimede
 *
 */
public final class Catalog {
	private static volatile Catalog instance = null;
	private Context ctx;
	private Document doc;
	private List<SuperMarketPOI> poiList;
	private String currentSuperMarketID = null;
	
	private Gondole currentCondole;
	
	
	private Map<String, String> colors;  
	private Map<String, ArrayList<String>> products; 
	private ArrayList<String> rayons;

	public Gondole getCurrentCondole() {
		return currentCondole;
	}

	public void setCurrentCondole(Gondole currentCondole) {
		this.currentCondole = currentCondole;
	}

	private Catalog(Context context) {
		super();
		this.ctx = context.getApplicationContext();
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db;
		try {
			db = dbf.newDocumentBuilder();
			this.doc = db.parse(this.ctx.getAssets().open("rayons.xml"));
			initRayonsXML();
			parsePOIs(db.parse(ctx.getAssets().open("supermarket_pois.xml")));
			
		} catch (ParserConfigurationException e) {
			Log.e("parse", "1");
			e.printStackTrace();
		} catch (SAXException e) {
			Log.e("parse", "2");
			e.printStackTrace();
		} catch (IOException e) {
			Log.e("parse", "3");
			e.printStackTrace();
		}
	}
	
	private void parsePOIs(Document doc) {
		NodeList nodes = doc.getElementsByTagName("node");
		poiList = new ArrayList<SuperMarketPOI>(nodes.getLength());
		for (int i=0; i<nodes.getLength(); i++) {
			poiList.add(SuperMarketPOI.deserialize((Element)nodes.item(i)));
			
		}
	}
	
	public final static Catalog getInstance() {
	    return Catalog.instance;
	}
	
	public List<SuperMarketPOI> getShops() {
		return poiList;
	}
	
	public final static Catalog init(Context context) {
		instance = new Catalog(context);
	    return Catalog.instance;
	}
	
	private void initRayonsXML() {
		colors = new HashMap<String, String>();
		products = new HashMap<String, ArrayList<String>>();
		rayons = new ArrayList<String>();
		
		NodeList rayonList = this.doc.getElementsByTagName("rayon");
		for(int index=0; index<rayonList.getLength(); index++){
			Element elem = (Element) rayonList.item(index);
			String type = elem.getAttribute("type");
			rayons.add(type);
			colors.put(type, elem.getAttribute("color"));

			ArrayList<String> productList = new ArrayList<String>();
			NodeList prods = elem.getElementsByTagName("produit");
			for(int i=0; i<prods.getLength(); i++){
				Element prodElem = (Element) prods.item(i);
				productList.add(prodElem.getAttribute("type"));
			}
			
			products.put(type, productList);

		}
	}
	
	public String getColor(String rayonType) {
//		NodeList rayons = this.doc.getElementsByTagName("rayon");
//		String color = "";
//		
//		for(int index=0; index<rayons.getLength(); index++){
//			Element elem = (Element) rayons.item(index); 
//			if(elem.hasAttribute("type") && elem.hasAttribute("color")
//					&& (elem.getAttribute("type").equals(rayonType))){
//				color = elem.getAttribute("color");
//				break;
//			}
//		}
//		Log.i("getColor", "rayon: " + rayonType + ", color: " + color);
//		return color;
		return colors.get(rayonType);
	}
	
	public ArrayList<String> getRayonsEdit(){
//		ArrayList<String> res = new ArrayList<String>();
//		NodeList rayons = this.doc.getElementsByTagName("rayon");
//		
//		for(int index=0; index<rayons.getLength(); index++){
//			Element elem = (Element) rayons.item(index); 
//			if(elem.hasAttribute("type")){
//				Log.i("CATALOG", "rayon : "+elem.getAttribute("type"));
//				res.add(elem.getAttribute("type"));
//			}
//		}
//		return res;
		return rayons;
	}
	
	public ArrayList<String> getRayonsView() {
		ArrayList<String> tmp = new ArrayList<String>(rayons);
		tmp.remove("Caisse");
		tmp.remove("Empty");
		tmp.remove("Entree");
		
		return tmp;
	}
	
	public ArrayList<String> getProducts(String rayonType){
//		ArrayList<String> res = new ArrayList<String>();
//		NodeList rayons = this.doc.getElementsByTagName("rayon");
//		Element elem = null;
//		
//		for(int index=0; index<rayons.getLength(); index++){
//			elem = (Element) rayons.item(index); 
//			if(elem.hasAttribute("type") && elem.getAttribute("type").equals(rayonType)){
//				break;
//			}
//		}
//		
//		NodeList prods = elem.getElementsByTagName("produit");
//		for(int index=0; index<prods.getLength(); index++){
//			elem = (Element) prods.item(index);
//			if(elem.hasAttribute("type")){
//				Log.i("CATALOG", rayonType+" product : "+elem.getAttribute("type"));
//				res.add(elem.getAttribute("type"));
//			}
//		}
//		
//		return res;
		return products.get(rayonType);
	} 
	
	////// Write maps back on sd :
	private File getBaseDir() {
		File rootDir = Environment.getExternalStorageDirectory();
		File baseDir = new File(rootDir, "insideloc");
		if (!baseDir.exists()) {
			baseDir.mkdirs();
		}
		
		return baseDir;
		
	}
	
	public boolean mapExists(String id) {
		File baseDir = getBaseDir();
		File filePath = new File(baseDir, id + ".xml");
		return filePath.exists();
	}
	
	public void copyEmptySM(String id) {
		String[] files = null;
		File baseDir = getBaseDir();
		File filePath = new File(baseDir, id + ".xml");

		InputStream in = null;
		OutputStream out = null;
		try {
			in = ctx.getAssets().open("empty_supermarket.xml");
			out = new FileOutputStream(filePath);
			copyFile(in, out);
			in.close();
			in = null;
			out.flush();
			out.close();
			out = null;
		} catch(Exception e) {
			Log.e("tag", e.getMessage());
		}       
	}

	private void copyFile(InputStream in, OutputStream out) throws IOException {
	    byte[] buffer = new byte[1024];
	    int read;
	    while((read = in.read(buffer)) != -1){
	      out.write(buffer, 0, read);
	    }
	}

	
	
//	public Document initMap(String id) {
//		copyEmptySM(id);
//		
//		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//		DocumentBuilder db = null;
//		Magasin magasin = null;
//
//		try {
//			db = dbf.newDocumentBuilder();
//			Document doc = db.newDocument();
//			//TODO : better init ?
//			doc.appendChild(doc.createElement("magasin"));
//			saveXMLMap(id, doc);
//			return doc;
//		} catch (ParserConfigurationException e) {
//			Log.e("parse", "1");
//			e.printStackTrace();
//		} catch (TransformerFactoryConfigurationError e) {
	//			Log.e("parse", "5");
	//		}
	//		return null;
	//	}

	public Document newDocument() {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = null;

		try {
			db = dbf.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return doc = db.newDocument();
	}
	
	public void saveXMLMap(String id, Document doc) {
		File baseDir = getBaseDir();
		File filePath = new File(baseDir, id + ".xml");
		Transformer t;
		try {
			t = TransformerFactory.newInstance().newTransformer();
		
		t.setOutputProperty(OutputKeys.INDENT, "yes");
		t.setOutputProperty(OutputKeys.METHOD, "xml");
		t.transform(new DOMSource(doc), new StreamResult(new FileOutputStream(filePath)));
		} catch (TransformerConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public Document getMap(String id) {
		File baseDir = getBaseDir();
		File filePath = new File(baseDir, id + ".xml");

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = null;
		Magasin magasin = null;

		try {
			db = dbf.newDocumentBuilder();
			if (filePath.exists()) {
				Document doc = db.parse(new FileInputStream(filePath));
				return doc;

			} else {
				Document doc = db.newDocument();
				//TODO : better init ?
						doc.appendChild(doc.createElement("magasin"));
						Transformer t = TransformerFactory.newInstance().newTransformer();
						t.setOutputProperty(OutputKeys.INDENT, "yes");
						t.setOutputProperty(OutputKeys.METHOD, "xml");
						t.transform(new DOMSource(doc), new StreamResult(new FileOutputStream(filePath)));
						return doc;
			}
		} catch (ParserConfigurationException e) {
			Log.e("parse", "1");
			e.printStackTrace();
		} catch (SAXException e) {
			Log.e("parse", "2");
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			Log.e("parse", "3");
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerConfigurationException e) {
					Log.e("parse", "4");
		} catch (TransformerFactoryConfigurationError e) {
					Log.e("parse", "5");
		} catch (TransformerException e) {
					Log.e("parse", "6");
		}
		return null;
	}

	public String getCurrentSuperMarketID() {
		return currentSuperMarketID;
	}

	public void setCurrentSuperMarketID(String currentSuperMarketID) {
		this.currentSuperMarketID = currentSuperMarketID;
	}
	
}

